package com.csx.data.orm.jpa.base.repositories;

import com.csx.data.orm.jpa.base.entity.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;

@Repository
public interface UserRepository extends CrudRepository<User, Long>, JpaSpecificationExecutor<User> {

    // ************************************ 查询数据 ******************************************************
    // 查询1: 根据 单个唯一键属性 查询获取 唯一数据. 1  —>  1
    Optional<User> findById(Long id);

    // 查询2: 根据 单个非唯一属性 查询获取 多条数据. 1  —>  n
    List<User> findByFirstNameIgnoreCase(String firstName);

    List<User> findByFirstNameIn(List<String> firstNames);

    // 查询3: 根据 多个非唯一属性 查询获取 唯一数据. n  —>  1
    Optional<User> findByFirstNameAndLastName(String firstName, String lastName);

    // 查询4: 根据 多个非唯一属性 查询获取 多条数据. n  —>  n
    List<User> findByAgeAndCity(int age, String city);

    // 查询5: 查询并排序
    List<User> findByFirstNameOrderByLastNameAsc(String firstName);

    List<User> findByFirstName(String firstName, Sort sort);

    // 查询6: 分页查询
    Page<User> findAll(Pageable pageable);

    // 查询7: 模糊查询
    List<User> findByFirstNameContainingIgnoreCase(String keyword);

    // 查询8: 通过 Specification 实现 多条件灵活查询(条件存在则拼接上去,否则不拼接该条件)
    List<User> findAll(Specification specification);

    // ************************************ 新增/修改数据 ******************************************************
    // 新增/修改1: 新增/修改 单条数据
    User save(User entity);

    // 新增/修改2: 新增/修改 多条数据
    <S extends User> List<S> saveAll(Iterable<S> entities);

    // ************************************ 删除数据 ******************************************************
    // 删除1: 根据 主键 删除 单条数据
    void deleteById(Long id);

    // 删除2: 根据 主键列表 删除 多条数据
    void deleteAllById(Iterable<? extends Long> ids);

    // 删除3: 根据 非主键 删除 多条数据
    @Modifying
    @Query("DELETE FROM User u WHERE u.lastName = :lastName")
    void deleteByLastName(@Param("lastName") String lastName);

    // 删除4: 根据 实体 删除数据
    void delete(User user);

    // 删除5: 根据 实体列表 删除数据
    void deleteInBatch(Iterable<User> users);

}
